package com.my.ph.entity.media;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import com.amilesend.mediainfo.lib.MediaInfoAccessor;
import com.amilesend.mediainfo.lib.MediaInfoLibrary;
import com.my.ph.media.info.VideoMediaInfo;
import lombok.Builder;
import lombok.Getter;
import lombok.experimental.Accessors;

import java.io.File;
import java.io.IOException;
import java.time.Duration;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

@Getter
@Accessors(chain = true)
@Builder
public class MediaInfo {

    private final static Map<Integer, String> MIN_WIDTHS_MAP = new LinkedHashMap<>(){{
        put(9600, "8640p");
        put(4608, "4320p");
        put(3200, "2160p");
        put(2240, "1440p");
        put(1600, "1080p");
        put(900, "720p");
        put(533, "480p");
    }};

    private final static Map<String, String> CHANNEL_LAYOUT_MAP = new HashMap<>(){{
        put("L R C LFE Ls Rs Lb Rb", "7.1");
        put("C L R LS RS LFE Cb", "5.1");
        put("L R C LFE Ls Rs", "5.1");
        put("C L R Ls Rs LFE", "5.1");
        put("L R", "2.0");
    }};

    private String originalTitle;
    private String enTitle;
    private Integer year;
    private String videoFormat;
    private String source;
    private String videoCodec;
    private String bitDepth;
    private String hdrFormat;
    private Double frameRate;
    private String audioCodec;
    private Integer channels;
    private String audioNum;
    private String team;

    private Integer season;
    private Integer episode;

    private boolean screeImage;

    private String titles;
    private String genresName;
    private String seasonName;
    private String episodeName;
    private String actingName;

    private Duration duration;
    private String inform;

    private File file;
    private String suffix;

    public static class MediaInfoBuilder {

        public String getVideoFormat(int width) {
            for (Map.Entry<Integer, String> entry : MIN_WIDTHS_MAP.entrySet()) {
                if (width >= entry.getKey()) {
                    return entry.getValue();
                }
            }
            return null;
        }

        public MediaInfo.MediaInfoBuilder videoMediaInfo(File inputFile) {
            MediaInfoLibrary mediaInfoLibrary = MediaInfoLibrary.newInstance();
            MediaInfoAccessor accessor = new MediaInfoAccessor(mediaInfoLibrary);
            try (VideoMediaInfo mediaInfo = new VideoMediaInfo(accessor).open(inputFile)){
                frameRate(mediaInfo.getFrameRate())
                    .file(inputFile)
                    .duration(mediaInfo.getDuration())
                    .bitDepth(mediaInfo.getBitDepth())
                    .audioCodec(mediaInfo.getAudioCodec())
                    .hdrFormat(mediaInfo.getHdrFormat())
                    .channels(mediaInfo.getChannels())
                    .inform(mediaInfo.getInform())
                    .audioNum(CHANNEL_LAYOUT_MAP.getOrDefault(mediaInfo.getChannelLayout(), "2.0"))
                    .videoCodec(mediaInfo.getVideoCodec())
                    .videoFormat(getVideoFormat(Math.max(mediaInfo.getWidth(), mediaInfo.getHeight())))
                    .suffix(FileUtil.getSuffix(inputFile));
                accessor.close();
                accessor.dispose();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            return this;
        }

    }

    public String getInform() {
        List<String> split = StrUtil.split(inform, "\n");
        String substring = split.stream().filter(s -> s.contains("Complete name")).findFirst()
                .filter(s -> s.contains(File.separator))
                .map(s -> s.substring(s.indexOf(":") + 1, s.lastIndexOf(File.separator) + 1)).orElse(null);
        if (StrUtil.isNotBlank(substring)) return inform.replace(substring, "");
        return inform;
    }
}
